/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TimeRecording.reporting;

import TimeRecording.business.HolidayCalculations;
import TimeRecording.tables.AllocationOfHours;
import TimeRecording.tables.Employee;
import TimeRecording.tables.MonthlyTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.view.JasperViewer;

/**
 *
 * @author david
 */
public class MonthEndSummaryReport {

    private final static String REPORT_NAME =
            "/reports/monthlysummary/MonthEndTime.jasper";
    
    private final static Logger LOGGER =
            Logger.getLogger(MonthEndSummaryReport.class.getName());
    
    // <editor-fold defaultstate="collapsed" desc="EmployeeSummaryDetail">
    public static class EmployeeSummaryDetail {
        
        private String name;

        private double salariedHours;
        private double additionalHours;
        private double sickness;
        private double leaveTaken;
        private double adjustments;
        private double sessionalHours;
        private double leaveEarned;

        public EmployeeSummaryDetail() {
        }

        public EmployeeSummaryDetail(
                    String name,
                    double salariedHours,
                    double additionalHours,
                    double sickness,
                    double leaveTaken,
                    double adjustments,
                    double sessionalHours,
                    double leaveEarned) {

            this.name = name;
            this.salariedHours = salariedHours;
            this.additionalHours = additionalHours;
            this.sickness = sickness;
            this.leaveTaken = leaveTaken;
            this.adjustments = adjustments;
            this.sessionalHours = sessionalHours;
            this.leaveEarned = leaveEarned;
        }

        public Double getAdditionalHours() {
            if (additionalHours > 0) {
                return additionalHours;
            } else {
                return null;
            }
        }

        public void setAdditionalHours(double additionalHours) {
            this.additionalHours = additionalHours;
        }

        public Double getAdjustments() {
            if (adjustments > 0) {
                return adjustments;
            } else {
                return null;
            }
        }

        public void setAdjustments(double adjustments) {
            this.adjustments = adjustments;
        }

        public Double getLeaveEarned() {
            if (leaveEarned > 0) {
                return leaveEarned;
            } else {
                return null;
            }
        }

        public void setLeaveEarned(double avEarned) {
            this.leaveEarned = avEarned;
        }

        public Double getLeaveTaken() {
            if (leaveTaken > 0) {
                return leaveTaken;
            } else {
                return null;
            }
        }

        public void setLeaveTaken(double avTaken) {
            this.leaveTaken = avTaken;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public double getSalariedHours() {
            return salariedHours;
        }

        public void setSalariedHours(double salariedHours) {
            this.salariedHours = salariedHours;
        }

        public Double getSickness() {
            if (sickness > 0) {
                return sickness;
            } else {
                return null;
            }
        }

        public void setSickness(double sickness) {
            this.sickness = sickness;
        }

        public Double getSessionalHours() {
            if (sessionalHours > 0) {
                return sessionalHours;
            } else {
                return null;
            }
        }

        public void setSessionalHours(double sessionalHours) {
            this.sessionalHours = sessionalHours;
        }

    } // </editor-fold>

    @SuppressWarnings("unchecked")
    public void viewReport(EntityManager entityManager, Date startOfMonth) {

        LOGGER.finer("viewReport (all employees)");
        
        List<Employee> employees = Employee.getActiveEmployees(entityManager);
        viewReport(employees, entityManager, startOfMonth);
    }

    @SuppressWarnings("unchecked")
    public void viewReport(Collection<Employee> employeesIn, 
            EntityManager entityManager, Date startOfMonth) {

        LOGGER.finer("viewReport (specific employees)");

        ArrayList<EmployeeSummaryDetail> employeesOut =
                new ArrayList<EmployeeSummaryDetail>();

        for (Employee employeeIn : employeesIn) {

            EmployeeSummaryDetail employeeOut = new EmployeeSummaryDetail();

            employeeOut.setName(employeeIn.getFriendlyName());

            MonthlyTime thisMonth = MonthlyTime.
                    getLatestPreStartDate(entityManager, startOfMonth, employeeIn);

            AllocationOfHours thisMonthsTime;
            if (thisMonth != null) {
                thisMonthsTime = thisMonth.getAllocation();
            } else {
                thisMonthsTime = new AllocationOfHours();
            }

            MonthlyTime lastMonth = MonthlyTime.
                    getLatestPreEndDate(entityManager,
                    thisMonth.getMonthlyTimePK().getStartDate(), employeeIn);

            employeeOut.setSalariedHours(
                    thisMonthsTime.getFixedExpected() +
                    thisMonthsTime.getFlexiExpected() +
                    thisMonthsTime.getSemiFlexiExpected());

            if (employeeOut.getSalariedHours() != 0.0) {
                employeeOut.setAdditionalHours(
                        thisMonthsTime.getSessionRecorded() +
                        thisMonthsTime.getAdHocRecorded());
            } else {
                employeeOut.setSessionalHours(
                        thisMonthsTime.getSessionRecorded() +
                        thisMonthsTime.getAdHocRecorded());
            }

            employeeOut.setSickness(
                    thisMonthsTime.getFixedSickness() +
                    thisMonthsTime.getFlexiSickness() +
                    thisMonthsTime.getSemiFlexiSickness() +
                    thisMonthsTime.getSessionSickness() +
                    thisMonthsTime.getAdHocSickness());

            employeeOut.setLeaveTaken(
                    thisMonthsTime.getFixedHoliday() +
                    thisMonthsTime.getFlexiHoliday() +
                    thisMonthsTime.getSemiFlexiHoliday() +
                    thisMonthsTime.getSessionHoliday() +
                    thisMonthsTime.getAdHocHoliday());

            if (lastMonth != null) {

                AllocationOfHours lastMonthsTime =
                        lastMonth.getAllocation();
                
                AllocationOfHours lastMonthsRevisedTime =
                        lastMonth.getRevisedAllocation();

                employeeOut.setAdjustments(
                        lastMonthsRevisedTime.getSessionRecorded() +
                        lastMonthsRevisedTime.getAdHocRecorded() -
                        lastMonthsTime.getSessionRecorded() -
                        lastMonthsTime.getAdHocRecorded());
            }

            employeeOut.setLeaveEarned(
                    HolidayCalculations.calculateHolidayEarned(
                            (employeeOut.getSessionalHours() != null ?
                                    employeeOut.getSessionalHours() : 0.0) +
                            (employeeOut.getAdjustments() != null ?
                                    employeeOut.getAdjustments() : 0.0)));

            employeesOut.add(employeeOut);
        }

        try {
            JasperReport template = (JasperReport)JRLoader.loadObject(
                    getClass().getResource(REPORT_NAME));

            JasperPrint report = JasperFillManager.fillReport(
                    template, new ReportingUtilities().getBasicParameters(),
                    new JRBeanCollectionDataSource(employeesOut));

            JasperViewer.viewReport(report, false);

        } catch (JRException ex) {
            Logger.getLogger(MonthEndSummaryReport.class.getName())
                    .log(Level.SEVERE, null, ex);
        }
    }
}
